package com.xqboss.apps.service.equipment;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xqboss.apps.constant.LockKey;
import com.xqboss.apps.domain.equipment.*;
import com.xqboss.apps.domain.member.SysUserNft;
import com.xqboss.apps.domain.nft.Nft;
import com.xqboss.apps.dto.equipment.*;
import com.xqboss.apps.enums.market.MarketTypeEnum;
import com.xqboss.apps.enums.nft.NftDispatchSourceEnum;
import com.xqboss.apps.enums.nft.UserNftStatusEnum;
import com.xqboss.apps.enums.user.*;
import com.xqboss.apps.service.nft.NftNumberService;
import com.xqboss.apps.service.nft.NftService;
import com.xqboss.apps.service.user.SysUserNftService;
import com.xqboss.apps.service.user.SysUserWalletService;
import com.xqboss.apps.service.user.UserAssetWrenchRecordService;
import com.xqboss.apps.vo.equipment.*;
import com.xqboss.common.core.domain.PageList;
import com.xqboss.common.core.redis.RedisCache;
import com.xqboss.common.core.redis.lock.LockValue;
import com.xqboss.common.core.redis.lock.RedisLock;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.common.utils.TransactionalManage;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xqboss.apps.mapper.equipment.EquipmentSmeltMapper;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 装备-熔炼(EquipmentSmelt)表服务实现类
 *
 * @author makejava
 * @since 2024-03-04 11:40:23
 */
@Service
public class EquipmentSmeltService extends ServiceImpl<EquipmentSmeltMapper, EquipmentSmelt> {

    @Autowired
    private EquipmentSmeltTemplateNftService smeltTemplateNftService;

    @Autowired
    private EquipmentSmeltTemplateService equipmentSmeltTemplateService;

    @Autowired
    private EquipmentSmeltTemplateProduceLuckyService equipmentSmeltTemplateProduceLuckyService;

    @Autowired
    private EquipmentSmeltConsumeService equipmentSmeltConsumeService;

    @Autowired
    private EquipmentSmeltProduceService equipmentSmeltProduceService;

    @Autowired
    private SysUserWalletService userWalletService;

    @Autowired
    private SysUserNftService userNftService;

    @Autowired
    private NftNumberService nftNumberService;

    @Autowired
    private UserAssetWrenchRecordService userAssetWrenchRecordService;

    @Autowired
    private NftService nftService;

    @Autowired
    private EquipmentService equipmentService;

    @Autowired
    private TransactionalManage transactionalManage;

    @Autowired
    private RedisCache redisCache;

    /**
     * 首页信息
     * @param userId
     * @return
     */
    public AppEquipmentSmeltIndexVo appIndex(Long userId) {
        EquipmentSmelt smelt = this.lambdaQuery()
                .eq(EquipmentSmelt::getUserId, userId)
                .orderByDesc(EquipmentSmelt::getId)
                .last("limit 1")
                .one();
        AppEquipmentSmeltIndexVo vo = new AppEquipmentSmeltIndexVo();
        if (smelt != null && smelt.getStatus() == 0) {
            int actualTime = smelt.getWaitingTime() - smelt.getFastTime();
            AppEquipmentSmeltVo smeltVo = new AppEquipmentSmeltVo();
            smeltVo.setId(smelt.getId());
            smeltVo.setRemainingMinutes(actualTime);
            smeltVo.setPerMinuteCostIntegral(smelt.getPerMinuteCostIntegral());
            smeltVo.setReceiveTime(smelt.getCreateTime().plusMinutes(actualTime));
            vo.setSmeltInfo(smeltVo);
            if (smeltVo.getReceiveTime().isAfter(LocalDateTime.now())) {
                // 最后3分钟不可加速
                if (smeltVo.getReceiveTime().isBefore(LocalDateTime.now().plusMinutes(3))) {
                    vo.setStatus(2);
                } else {
                    vo.setStatus(1);
                }
            } else {
                vo.setStatus(3);
            }

            // 消耗与产出
            List<EquipmentSmeltConsume> consumeList = equipmentSmeltConsumeService.lambdaQuery()
                    .eq(EquipmentSmeltConsume::getSmeltId, smelt.getId())
                    .list();
            List<EquipmentSmeltProduce> produceList = equipmentSmeltProduceService.lambdaQuery()
                    .ne(EquipmentSmeltProduce::getMethod, 3)
                    .eq(EquipmentSmeltProduce::getSmeltId, smelt.getId())
                    .list();
            smeltVo.setConsumeList(consumeList);
            smeltVo.setProduceList(produceList);
        } else {
            vo.setStatus(0);
        }
        // 查用户可熔炼的装备
        vo.setEquipmentList(smeltTemplateNftService.equipmentList(new EquipmentSmeltUserNftQueryDto(userId, null, null)));

        return vo;
    }


    /**
     * 保存
     * @param params
     */
    @SneakyThrows
    @RedisLock(lockKey = LockKey.LOCK_NFT_STOCK, lockByUser = true)
    public List<AppEquipmentSmeltEquipmentProduceVo> add(EquipmentSmeltSaveDto params) {
        // 验证
        params.setId(null);
        AppEquipmentSmeltWaitingVo waitingVo = getWaitingTime(params);
        EquipmentSmelt smelt = new EquipmentSmelt();
        smelt.setId(IdUtil.getSnowflakeNextId());
        smelt.setUserId(params.getUserId());
        smelt.setWaitingTime(waitingVo.getConsumeMinutes());
        smelt.setPerMinuteCostIntegral(waitingVo.getPerMinuteCostIntegral());

        // 算出产出，然后检查库存是否足够
        List<AppEquipmentSmeltEquipmentVo> equipmentList = smeltTemplateNftService.equipmentList(new EquipmentSmeltUserNftQueryDto(params.getUserId(), null, params.getUserNftIdList()));
        List<AppEquipmentSmeltEquipmentProduceVo> produceList = new ArrayList<>();
        for (AppEquipmentSmeltEquipmentVo t : equipmentList) {
            produceList.addAll(t.getProduceList());
        }
        // 整合produceList中的资源id相同的数据，数量相加合并
        produceList = produceList.stream().collect(
                Collectors.toMap(AppEquipmentSmeltEquipmentProduceVo::getSourceId, Function.identity(), (p1, p2) -> {
                    p1.setSourceNum(p1.getSourceNum() + p2.getSourceNum());
                    return p1;
                })).values().stream().collect(Collectors.toList());
        // 实际消耗数据
        List<EquipmentSmeltConsume> actualConsumeList = new ArrayList<>();
        // 实际产出数据
        List<EquipmentSmeltProduce> actualProduceList = new ArrayList<>();

        for (AppEquipmentSmeltEquipmentVo t : equipmentList) {
            // 实际消耗数据
            EquipmentSmeltConsume consume = BeanUtil.copyProperties(t, EquipmentSmeltConsume.class);
            consume.setSmeltId(smelt.getId());
            consume.setUserId(smelt.getUserId());
            actualConsumeList.add(consume);
        }

        // 算出幸运产出，返回redis的k-v
        List<Pair<String, Long>> luckyKeyAndCount = getLuckProduceList(params.getUserId(), actualConsumeList, produceList);

        List<AppEquipmentSmeltEquipmentProduceVo> finalProduceList = produceList;
        transactionalManage.executeWithException(() -> {
            // 锁库存
            for (AppEquipmentSmeltEquipmentProduceVo t : finalProduceList) {
                if (t.getType() == MarketTypeEnum.NORMAL || t.getType() == MarketTypeEnum.EQUIPMENT) {
                    try {
                        nftService.lockStock(t.getSourceId(), t.getSourceNum().intValue());
                    } catch (Exception e) {
                        throw new ServiceException("熔炼可获得材料不足，请联系客服");
                    }
                }
                // 实际产出数据
                EquipmentSmeltProduce produce = BeanUtil.copyProperties(t, EquipmentSmeltProduce.class);
                produce.setSmeltId(smelt.getId());
                produce.setUserId(smelt.getUserId());
                actualProduceList.add(produce);
            }
            // 保存记录
            this.save(smelt);
            // 销毁装备
            userNftService.userNftBurn(params.getUserId(), params.getUserNftIdList(), UserNftStatusEnum.SMELT_BURN);
            // 保存数据
            if (!actualConsumeList.isEmpty()) {
                equipmentSmeltConsumeService.saveBatch(actualConsumeList);
            }
            if (!actualProduceList.isEmpty()) {
                equipmentSmeltProduceService.saveBatch(actualProduceList);
            }
            // 如果有传加速时间，则需要加速
            if (params.getSpeedUpMinute() != null && params.getSpeedUpMinute() > 0) {
                EquipmentSmeltSpeedUpDto speedUpDto = new EquipmentSmeltSpeedUpDto();
                speedUpDto.setUserId(params.getUserId());
                speedUpDto.setId(smelt.getId());
                speedUpDto.setCostIntegral(null);
                speedUpDto.setSpeedUpMinute(params.getSpeedUpMinute());
                speedUp(speedUpDto);
            }
            return true;
        });

        // 幸运计数存入缓存
        if (!luckyKeyAndCount.isEmpty()) {
            for (Pair<String, Long> t : luckyKeyAndCount) {
                redisCache.setCacheObject(t.getKey(), t.getValue());
            }
        }
        // 如果等待时间是0或者加速时间等于等待时间，则直接领取
        if (smelt.getWaitingTime() == 0 || (params.getSpeedUpMinute() != null && params.getSpeedUpMinute().equals(smelt.getWaitingTime()))) {
            return receive(smelt.getId());
        }
        return new ArrayList<>();
    }

    /**
     * 加速熔炼
     * @param params
     */
    @SneakyThrows
    @RedisLock(lockKey = LockKey.LOCK_USER_WALLET, lockByUser = true)
    public long speedUp(EquipmentSmeltSpeedUpDto params) {
        EquipmentSmelt smelt = this.getById(params.getId());
        if (smelt == null || params.getSpeedUpMinute() < 1) {
            throw new ServiceException("参数错误");
        }
        // 领取时间的最后3分钟无法加速
        long actualTime = ChronoUnit.SECONDS.between(LocalDateTime.now(), smelt.getCreateTime().plusMinutes(smelt.getWaitingTime() - smelt.getFastTime()));
        if (actualTime <= 3 * 60) {
            throw new ServiceException("无法加速");
        } else {
            actualTime = BigDecimal.valueOf(actualTime).divide(BigDecimal.valueOf(60), 0, RoundingMode.UP).longValue();
        }
        // 加速分钟数-剩余等待分钟数>=2分钟，则无法加速
        if (params.getSpeedUpMinute() - actualTime >= 2) {
            throw new ServiceException("请重新尝试加速");
        }
        // 验证加速分钟消耗的热豆是否对应
        if (params.getCostIntegral() != null && smelt.getPerMinuteCostIntegral().multiply(BigDecimal.valueOf(params.getSpeedUpMinute())).compareTo(params.getCostIntegral()) != 0) {
            throw new ServiceException("参数错误");
        } else if (params.getCostIntegral() == null) {
            params.setCostIntegral(smelt.getPerMinuteCostIntegral().multiply(BigDecimal.valueOf(params.getSpeedUpMinute())));
        }

        transactionalManage.executeWithException(() -> {
            // 扣除热豆
            userWalletService.reduce(params.getUserId(), UserWalletEnum.INTEGRAL, params.getCostIntegral(),
                    WalletChangeTypeEnum.SMELT_SPEEDUP, smelt.getId(), WalletChangeTypeEnum.SMELT_SPEEDUP.getMsg());
            // 更新数据
            smelt.setFastTime(smelt.getFastTime() + params.getSpeedUpMinute());
            this.updateById(smelt);
            return true;
        });

        // 返回剩余分钟数
        return Math.max(actualTime - params.getSpeedUpMinute(), 0L);

    }


    /**
     * 领取
     * @param id
     */
    @SneakyThrows
    @RedisLock(lockKey = LockKey.LOCK_SMELT_RECEIVE)
    public List<AppEquipmentSmeltEquipmentProduceVo> receive(@LockValue Long id) {
        EquipmentSmelt smelt = this.getById(id);
        if (smelt == null || smelt.getStatus() != 0) {
            throw new ServiceException("参数错误");
        }
        // 验证是否到时间
        int actualTime = smelt.getWaitingTime() - smelt.getFastTime();
        Date receiveTime = DateUtil.offsetMinute(Date.from(smelt.getCreateTime().atZone(ZoneId.systemDefault()).toInstant()), actualTime);
        if (receiveTime.after(new Date())) {
            throw new ServiceException("未到时间");
        }
        List<EquipmentSmeltProduce> produceList = equipmentSmeltProduceService.lambdaQuery()
                .eq(EquipmentSmeltProduce::getSmeltId, smelt.getId())
                .list();

        transactionalManage.executeWithException(() -> {
            // 更新状态
            boolean result = this.lambdaUpdate()
                    .eq(EquipmentSmelt::getId, smelt.getId())
                    .eq(EquipmentSmelt::getStatus, 0)
                    .set(EquipmentSmelt::getStatus, 1)
                    .set(EquipmentSmelt::getReceiveTime, new Date())
                    .update();
            if (!result) {
                throw new ServiceException("领取失败");
            }
            // 发放产出
            for (EquipmentSmeltProduce t : produceList) {
                switch (t.getType()) {
                    case NORMAL:
                    case EQUIPMENT: {
                        Nft nft = nftService.requireNft(t.getSourceId());
                        LocalDateTime saleableTime = LocalDateTime.now().plusMinutes(Optional.ofNullable(nft.getCoolingTime()).orElse(0));
                        nftService.takeStock(t.getSourceId(), t.getSourceNum().intValue());
                        nftNumberService.distributeNftNumber(t.getUserId(), t.getSourceId(), smelt.getId(), t.getId(), t.getSourceNum().intValue(), true, saleableTime, NftDispatchSourceEnum.SMELT, UserNftSourceTypeEnum.SMELT);
                    }
                    break;
                    case MATERIAL: {
                        if (UserWalletEnum.valueOf(Math.toIntExact(t.getSourceId())) == UserWalletEnum.INTEGRAL) {
                            userWalletService.increase(t.getUserId(), UserWalletEnum.valueOf(Math.toIntExact(t.getSourceId())), BigDecimal.valueOf(t.getSourceNum()), WalletChangeTypeEnum.SMELT_PRODUCE, t.getId(), WalletChangeTypeEnum.SMELT_PRODUCE.getMsg());
                        } else if (UserWalletEnum.valueOf(Math.toIntExact(t.getSourceId())) == UserWalletEnum.WRENCH) {
                            userAssetWrenchRecordService.updateWrenchBalance(t.getUserId(), WalletWrenchChangeTypeEnum.SMELT_PRODUCE, WalletChangeDirectionEnum.IN, BigDecimal.valueOf(t.getSourceNum()), t.getId(), WalletWrenchChangeTypeEnum.SMELT_PRODUCE.getMsg());
                        }
                    }
                    break;
                }
            }
            return true;
        });
        // 将产出转换成vo
        return produceList.stream().map(t -> BeanUtil.copyProperties(t, AppEquipmentSmeltEquipmentProduceVo.class)).collect(Collectors.toList());
    }


    /**
     * 计算幸运产出
     * @param userId
     * @param actualConsumeList
     * @return
     */
    private List<Pair<String, Long>> getLuckProduceList(Long userId, List<EquipmentSmeltConsume> actualConsumeList, List<AppEquipmentSmeltEquipmentProduceVo> produceList) {
        List<Pair<String, Long>> result = new ArrayList<>();
        // 同一个templateId的数据放一起,计数，组合一个map
        Map<Long, Long> consumeTemplateMap = actualConsumeList.stream()
                .collect(Collectors.groupingBy(EquipmentSmeltConsume::getTemplateId, Collectors.counting()));
        // 查出这些templateId对应的幸运产出，分组成一个map
        Map<Long , List<EquipmentSmeltTemplateProduceLucky>> luckyProduceListMap = equipmentSmeltTemplateProduceLuckyService.lambdaQuery()
                .in(EquipmentSmeltTemplateProduceLucky::getTemplateId, consumeTemplateMap.keySet())
                .list()
                .stream()
                .collect(Collectors.groupingBy(EquipmentSmeltTemplateProduceLucky::getTemplateId));
        // 遍历consumeTemplateMap，根据luckyProduceListMap中的数据，计算出幸运产出
        for (Map.Entry<Long, Long> entry : consumeTemplateMap.entrySet()) {
            List<EquipmentSmeltTemplateProduceLucky> luckyList = luckyProduceListMap.get(entry.getKey());
            if (luckyList == null || luckyList.isEmpty()) {
                continue;
            }
            long consumeNum = entry.getValue();
            for (EquipmentSmeltTemplateProduceLucky t : luckyList) {
                // 计算幸运产出，从redis里取出计数，如果大于等于触发门槛，则触发一次按概率产出幸运藏品，如果产出了，则计数清零
                String redisKey = generateRedisKey(userId, t.getTemplateId(), t.getId());
                Long count = redisCache.getCacheObject(redisKey);
                if (count == null) {
                    count = 0L;
                }
                // 算出理论产出幸运藏品个数
                long produceNum = (count + consumeNum) / t.getTriggerCount();
                if (produceNum >= 1) {
                    // 验证库存是否充足
                    if (t.getType() == MarketTypeEnum.NORMAL || t.getType() == MarketTypeEnum.EQUIPMENT) {
                        Nft nft = nftService.requireNft(t.getSourceId());
                        if (nft.getStock() < produceNum) {
                            throw new ServiceException("幸运材料库存不足，请联系客服");
                        }
                    }
                };
                // 产出个数
                int productNum = 0;
                // 循环consumeNum次，每次都判断是否触发幸运产出
                for (int i = 0; i < consumeNum; i++) {
                    count++;
                    if (count >= t.getTriggerCount()) {
                        // 触发幸运产出.rate是概率，最低是0，最高是1，最多5位小数
                        if (t.getRate().compareTo(BigDecimal.ZERO) > 0 && t.getRate().compareTo(BigDecimal.ONE) <= 0) {
                            BigDecimal bd = BigDecimal.valueOf(Math.random()).setScale(5, RoundingMode.HALF_UP);
                            if (t.getRate().compareTo(bd) >= 0) {
                                productNum++;
                                // 产出了，计数清零
                                count = 0L;
                            }
                        }
                    }
                }
                if (productNum > 0) {
                    AppEquipmentSmeltEquipmentProduceVo produce = BeanUtil.copyProperties(t, AppEquipmentSmeltEquipmentProduceVo.class);
                    produce.setMethod(3);
                    produce.setSourceNum((double) productNum * produce.getSourceNum());
                    // 加到最前面
                    produceList.add(0, produce);
                }
                // result存入key和count，最后所有执行成功事务提交后再设置redis
                result.add(Pair.of(redisKey, count));
            }
        }
        return result;
    }

    /**
     * 生成幸运产出计数的redis key
     * @param userId
     * @param templateId
     * @param luckyProduceId
     * @return
     */
    private String generateRedisKey(Long userId, Long templateId, Long luckyProduceId) {
        return "smelt:" + userId + ":" + templateId + ":" + luckyProduceId;
    }

    /**
     * 获取熔炼时长和加速消耗
     * @param params
     * @return
     */
    public AppEquipmentSmeltWaitingVo getWaitingTime(EquipmentSmeltSaveDto params) {
        AppEquipmentSmeltWaitingVo vo = new AppEquipmentSmeltWaitingVo();
        // 用户热豆数
        vo.setIntegral(userWalletService.getWallet(params.getUserId(), UserWalletEnum.INTEGRAL).getAmount());
        // 如果传了id，说明是加速，没传id，说明是新熔炼
        if (params.getId() != null) {
            EquipmentSmelt smelt = this.getById(params.getId());
            if (smelt == null || smelt.getStatus() != 0) {
                throw new ServiceException("参数错误");
            }
            long actualTime = ChronoUnit.SECONDS.between(LocalDateTime.now(), smelt.getCreateTime().plusMinutes(smelt.getWaitingTime() - smelt.getFastTime()));
            if (actualTime <= 0) {
                vo.setConsumeMinutes(0);
            } else {
                actualTime = BigDecimal.valueOf(actualTime).divide(BigDecimal.valueOf(60), 0, RoundingMode.UP).longValue();
                vo.setConsumeMinutes((int) actualTime);
            }
            vo.setPerMinuteCostIntegral(smelt.getPerMinuteCostIntegral());
            return vo;
        } else if (params.getUserNftIdList() != null && !params.getUserNftIdList().isEmpty()) {
            List<SysUserNft> userNftList = userNftService.lambdaQuery()
                    .eq(SysUserNft::getUserId, params.getUserId())
                    .in(SysUserNft::getId, params.getUserNftIdList())
                    .eq(SysUserNft::getNftStatus, UserNftStatusEnum.NORMAL)
                    .list();
            if (userNftList.isEmpty() || userNftList.size() != params.getUserNftIdList().size()) {
                throw new ServiceException("用户藏品不存在");
            }
            List<EquipmentSmeltTemplateNft> templateNftList = smeltTemplateNftService.lambdaQuery()
                    .in(EquipmentSmeltTemplateNft::getNftId, userNftList.stream().map(SysUserNft::getNftId).collect(Collectors.toList()))
                    .list();
            Set<Long> nftIdSet = userNftList.stream().map(SysUserNft::getNftId).collect(Collectors.toSet());
            if (templateNftList.isEmpty() || templateNftList.size() != nftIdSet.size()) {
                throw new ServiceException("用户藏品不可熔炼");
            }
            // 计算
            Map<Long, EquipmentSmeltTemplate> templateMap = equipmentSmeltTemplateService.lambdaQuery()
                    .in(EquipmentSmeltTemplate::getId, templateNftList.stream().map(EquipmentSmeltTemplateNft::getTemplateId).collect(Collectors.toList()))
                    .list()
                    .stream()
                    .collect(Collectors.toMap(EquipmentSmeltTemplate::getId, t -> t));
            Map<Long, Long> nftIdTemplateIdMap = templateNftList.stream().collect(Collectors.toMap(EquipmentSmeltTemplateNft::getNftId, EquipmentSmeltTemplateNft::getTemplateId));
            Integer totalWaitingTime = 0;
            Double totalCostIntegral = 0D;
            for (SysUserNft t :userNftList) {
                EquipmentSmeltTemplate template = templateMap.get(nftIdTemplateIdMap.get(t.getNftId()));
                totalWaitingTime += template.getWaitingTime();
                totalCostIntegral += template.getWaitingTime()*template.getFastCostIntegral();
            }
            vo.setConsumeMinutes(totalWaitingTime);
            if (totalWaitingTime != 0) {
                vo.setPerMinuteCostIntegral(BigDecimal.valueOf(totalCostIntegral).divide(BigDecimal.valueOf(totalWaitingTime), 2, RoundingMode.HALF_UP));
            } else {
                vo.setPerMinuteCostIntegral(BigDecimal.ZERO);
            }
        } else {
            throw new ServiceException("至少添加一件熔炼装备");
        }
        return vo;
    }

    /**
     * 分页列表
     * @param params
     * @return
     */
    public PageList<AppEquipmentSmeltDetailVo> pageList(EquipmentSmeltRecordQueryDto params) {
        PageList<AppEquipmentSmeltDetailVo> pageList = new PageList<>();
        List<AppEquipmentSmeltDetailVo> list = new ArrayList<>();
        Page<EquipmentSmelt> page = this.lambdaQuery()
                .eq(EquipmentSmelt::getUserId, params.getUserId())
                .ne(EquipmentSmelt::getStatus, 0)
                .orderByDesc(EquipmentSmelt::getId)
                .page(new Page<>(params.getPageNum(), params.getPageSize()));
        if (page.getRecords().isEmpty()) {
            return pageList;
        }
        for (EquipmentSmelt t : page.getRecords()) {
            AppEquipmentSmeltDetailVo detailVo = new AppEquipmentSmeltDetailVo();
            detailVo.setId(t.getId());
            detailVo.setCreateTime(t.getCreateTime());
            detailVo.setProduceList(equipmentSmeltProduceService.lambdaQuery()
                    .eq(EquipmentSmeltProduce::getSmeltId, t.getId())
                    .orderByDesc(EquipmentSmeltProduce::getMethod)
                    .list()
            );
            // 消耗需要根据nftId分组，然后统计相同nftId的数量构建新的list
            List<EquipmentSmeltConsume> consumeList = equipmentSmeltConsumeService.lambdaQuery()
                    .eq(EquipmentSmeltConsume::getSmeltId, t.getId())
                    .list();
            List<AppEquipmentSmeltConsumeGroupVo> consumeGroupList = consumeList.stream()
                    .collect(Collectors.groupingBy(EquipmentSmeltConsume::getNftId))
                    .entrySet()
                    .stream()
                    .map(entry -> {
                        AppEquipmentSmeltConsumeGroupVo groupVo = new AppEquipmentSmeltConsumeGroupVo();
                        groupVo.setNftId(entry.getKey());
                        groupVo.setNftTitle(entry.getValue().get(0).getNftTitle());
                        groupVo.setNftMainImg(entry.getValue().get(0).getNftMainImg());
                        groupVo.setNftNum(entry.getValue().size());
                        return groupVo;
                    })
                    .collect(Collectors.toList());
            detailVo.setConsumeGroupList(consumeGroupList);
            list.add(detailVo);
        }
        pageList.setTotal(page.getTotal());
        pageList.setList(list);
        return pageList;
    }

    /**
     * 消耗详情列表
     * @param params
     * @return
     */
    public List<AppEquipmentSmeltConsumeDetailVo> consumeDetailList(EquipmentSmeltRecordConsumeQueryDto params) {
        List<EquipmentSmeltConsume> consumeList = equipmentSmeltConsumeService.lambdaQuery()
                .eq(EquipmentSmeltConsume::getSmeltId, params.getId())
                .eq(EquipmentSmeltConsume::getUserId, params.getUserId())
                .eq(EquipmentSmeltConsume::getNftId, params.getNftId())
                .list();
        if (consumeList.isEmpty()) {
            return new ArrayList<>();
        }
        List<AppEquipmentSmeltConsumeDetailVo> list = new ArrayList<>();
        for (EquipmentSmeltConsume t : consumeList) {
            AppEquipmentSmeltConsumeDetailVo vo = BeanUtil.copyProperties(t, AppEquipmentSmeltConsumeDetailVo.class);
            // 设置装备信息
            AppEquipmentSmeltConsumeDetailVo.EquipmentVo equipmentVo = BeanUtil.copyProperties(equipmentService.getByNftNumberId(t.getNftNumberId()), AppEquipmentSmeltConsumeDetailVo.EquipmentVo.class);
            vo.setEquipmentInfo(equipmentVo);
            list.add(vo);
        }
        return list;
    }
}
